from __future__ import annotations

from typing import TYPE_CHECKING

from ... import Command
from ...batoceraPaths import CONFIGS, SAVES, SCREENSHOTS, mkdir_if_not_exists
from ...controller import generate_sdl_game_controller_config
from ...exceptions import InvalidConfiguration
from ...utils.buildargs import parse_args
from ...utils.configparser import CaseSensitiveConfigParser
from ..Generator import Generator

if TYPE_CHECKING:
    from pathlib import Path

    from ...types import HotkeysContext


class EDuke32Generator(Generator):

    def getHotkeysContext(self) -> HotkeysContext:
        return {
            "name": "eduke32",
            "keys": { "exit": "killall -9 eduke32; killall -9 fury", "menu": "KEY_ESC", "pause": "KEY_ESC", "save_state": "KEY_F6", "restore_state": "KEY_F9" }
        }

    def generate(self, system, rom, playersControllers, metadata, guns, wheels, gameResolution):
        # Core is either eduke32 or fury
        core = system.config.core
        config_dir = CONFIGS / f"{core}"
        saves_dir = SAVES / f"{core}"
        config_file = config_dir / f"{core}.cfg"
        # A script file with console commands that are always ran when the game starts
        script_file = config_dir / "autoexec.cfg"

        mkdir_if_not_exists(config_dir)
        mkdir_if_not_exists(saves_dir)

        if not config_file.exists():
            with config_file.open('x'):
                pass

        parser = CaseSensitiveConfigParser(interpolation=None)
        # Configuration options found here: https://wiki.eduke32.com/wiki/Configuration_file_options
        # NB: Not all configuration options listed actually work e.g. showFPS, etc.
        # NB: In eduke32 configs, booleans must be integers
        with config_file.open("r") as config:
            parser.read_file(config)
        if not parser.has_section("Screen Setup"):
            parser.add_section("Screen Setup")
        parser.set("Screen Setup", "ScreenWidth", str(gameResolution["width"]))
        parser.set("Screen Setup", "ScreenHeight", str(gameResolution["height"]))
        # The game should always be fullscreen
        parser.set("Screen Setup", "ScreenMode", "1")
        with config_file.open("w") as config:
            parser.write(config)
        with script_file.open("w") as script:
            script.write(
                f'// This file is automatically generated by eduke32Generator.py\n'
                f'bind "F12" "screenshot"\n'
                f'screenshot_dir "{SCREENSHOTS}"\n'
                f'r_showfps "{1 if system.config.show_fps else 0}"\n'
                f'echo BATOCERA\n'  # Easy check when debugging
            )
        launch_args: list[str | Path] = [
            core,
            "-cfg", config_file,
            "-nologo" if system.config.get_bool("nologo") else ""
        ]
        if core == "fury":
            launch_args += [
                "-gamegrp", rom.name,
                "-j", rom.parent,
            ]
        else:
            result = parse_args(launch_args, rom)
            if not result.okay:
                raise InvalidConfiguration(result.message)
        return Command.Command(
            array=launch_args,
            env={
                'SDL_GAMECONTROLLERCONFIG': generate_sdl_game_controller_config(playersControllers)
            }
        )
